// Copyright 2013 Ronald Schlenker, www.technewlogic.de.
// 
// This file is part of Byond.
// 
// Byond is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
// 
// Byond is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with Byond.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Threading;
using Byond.AudioMidi;
using Byond.Logging;
using Mvvm;
using Utils;
using Utils.Messaging;

namespace Byond.Frontend.ViewModels
{
	internal class LiveViewModel : ViewModelBase, IDisposable
	{
		private readonly RuntimeInfo _runtimeInfo;
		private readonly MenuItemRegistrar _menuItemRegistrar;
		private readonly IUserLogger _logger;
		private readonly IEnsembleRunner _ensembleRunner;
		private readonly UiDispatcher _dispatcher;

		public LiveViewModel(Control patchControl, string patchName)
		{
			PatchControl = patchControl;
			PatchName = patchName;
		}

		private void Ctor()
		{
			_logger.NewLogMessage += OnLogMessage;

			// Wenn das nicht gemacht wird, wird das DataTemplate im ItemsControl ignoriert.
			MenuItems = _menuItemRegistrar.MenuItems
				.Select(it => new { UiElement = it() })
				.ToList();

			var timer = new DispatcherTimer
			{
				Interval = TimeSpan.FromMilliseconds(500),
				IsEnabled = true
			};
			timer.Tick += (s, e) =>
				{
					OnPropertyChanged("AudioCpuLoad");
					OnPropertyChanged("UiCpuLoad");
				};
			_runtimeInfo.VoicesCountChanged += () => OnPropertyChanged("VoicesCount");
		}

		public event MessageEventHandler SendMessage;

		public Control PatchControl { get; private set; }
		public string PatchName { get; private set; }

		public IEnumerable<object> MenuItems { get; private set; }

		private string _logMessage1;
		public string LogMessage1
		{
			get { return _logMessage1; }
			set
			{
				_logMessage1 = GetFirstLine(value);
				OnPropertyChanged("LogMessage1");
			}
		}

		private string _logMessage2;
		public string LogMessage2
		{
			get { return _logMessage2; }
			set
			{
				_logMessage2 = GetFirstLine(value);
				OnPropertyChanged("LogMessage2");
			}
		}

		private string _logMessage3;
		public string LogMessage3
		{
			get { return _logMessage3; }
			set
			{
				_logMessage3 = GetFirstLine(value);
				OnPropertyChanged("LogMessage3");
			}
		}

		public string AudioCpuLoad { get { return _runtimeInfo.AudioCpuLoad.ToString("P1"); } }
		public string UiCpuLoad { get { return _runtimeInfo.UiCpuLoad.ToString("P1"); } }
		public string VoicesCount { get { return _runtimeInfo.VoicesCount.ToString(); } }

		private void OnLogMessage(string message)
		{
			_dispatcher.BeginInvokeIfInitialized(() =>
				{
					LogMessage1 = _logMessage2;
					LogMessage2 = _logMessage3;
					LogMessage3 = message;
				});
		}

		public void GotoCode()
		{
			SendMessage(new ShowViewRequest(typeof(CodeEditorViewModel)));
		}

		public void Stop()
		{
			_ensembleRunner.Stop();
		}

		private static string GetFirstLine(string value)
		{
			return String.IsNullOrWhiteSpace(value) ? value : value.Replace("\r\n", "  -  ");
		}

		public void Dispose()
		{
			_logger.NewLogMessage -= OnLogMessage;
			PatchControl = null;
		}
	}
}